package fr.mehfile.view;

import static fr.mehfile.api.gcm.CommonUtilities.SENDER_ID;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Handler;

import com.google.android.gcm.GCMRegistrar;

import fr.mehfile.R;
import fr.mehfile.api.gcm.ServerUtilities;
import fr.mehfile.api.update.UpdateListener;
import fr.mehfile.api.update.UpdateTask;
import fr.mehfile.view.utils.Utils;

/**
 * @author nazaraly
 * 
 */
public class SplashScreen extends Activity implements UpdateListener {
	private static final String TAG = "SplashScreen";
	AsyncTask<Void, Void, Void> mRegisterTask=null;
	private boolean timeElapsed = false;
	// temps minimum de l'affichage du splashscreen si pas de reseau ou en mode
	// itinerance
	private static long MIN_TIME_TO_DISPLAY = 2000;
	// temps maximum du splashscreen
	private static long MAX_TIME_TO_DISPLAY = 6000;
	private Handler handler;
	private long timeStarted = 0;

	/**
	 * 
	 */
	private Runnable splashScreenTimeElapsedRunnable = new Runnable() {

		public void run() {
			onSplashScreenTimeElapsed();

		}
	};

	/**
	 * lancement de l'ecran accueil si le temps d'affichage du splashscreen est
	 * ecoulee
	 */
	private Runnable splashScreenEndRunnable = new Runnable() {

		public void run() {
			// splashScreen end
			launchHomeScreen();
			finish();

		}
	};

	/**
	 * lancement de l'ecran accueil si une erreur a eu lieu lors de la mise a
	 * jour des donnee
	 */
	private Runnable splashScreenEndWithErrorRunnable = new Runnable() {

		public void run() {
			// error
			launchHomeScreen();
			finish();
		}
	};

	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.splashscreen);

		handler = new Handler();
		NetworkInfo networkType = ((ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE))
				.getActiveNetworkInfo();
		// reseau disponible et n'est pas en mode itinerance?
		if ((networkType != null) && networkType.isAvailable()
				&& !networkType.isRoaming()) {
			// on veut que la classe SplashScreen soit avertit du statut de la
			// mise e jour des donnees
			UpdateTask.getInstance(this).addListener(this);
			Utils.debugger.logDebug(TAG,
					"Network available, launch launchMainTask");
			try{
			registerGcm();
			}catch(Exception e){
				e.printStackTrace();
			}
			// lancement de la mise a jour des donnees
			UpdateTask.getInstance(this).launchMainTask(this);
			timeStarted = System.currentTimeMillis();
			// lancement de l'ecran acceuil au bout du temps maximum declare
			handler.postDelayed(splashScreenTimeElapsedRunnable,
					MAX_TIME_TO_DISPLAY);
		} else {
			Utils.debugger.logDebug(TAG,
					"Network not available, launch launchMainTask");
			timeStarted = System.currentTimeMillis();
			// pas de reseau ou en mode itinerance donc affichage de l'ecran
			// acceuil au bout du temps minimum declare
			handler.postDelayed(splashScreenTimeElapsedRunnable,
					MIN_TIME_TO_DISPLAY);

		}
	}

	@Override
	protected void onDestroy() {

		// supression de tous les callbacks et de l'ecoute du statut de la mise
		// a
		// jour des donnee
		UpdateTask.getInstance(this).removeListener(this);
		handler.removeCallbacks(this.splashScreenTimeElapsedRunnable);
		handler.removeCallbacks(this.splashScreenEndRunnable);
		handler.removeCallbacks(this.splashScreenEndWithErrorRunnable);
		
		 if (mRegisterTask != null) {
	            mRegisterTask.cancel(true);
	        }
		
	   //     GCMRegistrar.onDestroy(this);

		super.onDestroy();
	}
	
	private void registerGcm(){
		
	    // Make sure the device has the proper dependencies.
        GCMRegistrar.checkDevice(this);
        GCMRegistrar.checkManifest(this);
        
        final String regId = GCMRegistrar.getRegistrationId(this);
        if (regId.equals("")) {
            // Automatically registers application on startup.
        	Utils.debugger.logDebug(TAG, "register app on startup");
            GCMRegistrar.register(getApplicationContext(), SENDER_ID);
        } else {
        	Utils.debugger.logDebug(TAG, "Device is already registered on GCM, check server");
            if (!GCMRegistrar.isRegisteredOnServer(this)) {
                // Try to register again, but not in the UI thread.
                // It's also necessary to cancel the thread onDestroy(),
                // hence the use of AsyncTask instead of a raw thread.
                final Context context = this;
                mRegisterTask = new AsyncTask<Void, Void, Void>() {

                    @Override
                    protected Void doInBackground(Void... params) {
                        boolean registered =
                                ServerUtilities.register(context, regId);
                        // At this point all attempts to register with the app
                        // server failed, so we need to unregister the device
                        // from GCM - the app will try to register again when
                        // it is restarted. Note that GCM will send an
                        // unregistered callback upon completion, but
                        // GCMIntentService.onUnregistered() will ignore it.
                        if (!registered) {
                            GCMRegistrar.unregister(context);
                        }
                        return null;
                    }

                    @Override
                    protected void onPostExecute(Void result) {
                        mRegisterTask = null;
                    }

                };
                mRegisterTask.execute(null, null, null);
            }
        }
	}

	/**
	 * methode appele si temps impartit pour l'affichage du splashscreen est
	 * ecoule
	 */
	private void onSplashScreenTimeElapsed() {
		if (timeElapsed == false) {
			Utils.debugger.logDebug(TAG, "Maximum time elapsed");
			// variable timeElapsed est mise a vrai pour que la methode
			// onUpdateComplete ou onUpdateError soit
			// execute
			timeElapsed = true;
			try {
				// vu que le temps maximum est ecoule, on ne veut plus etre
				// avertit du statut de la mise a jour des donnee
				UpdateTask.getInstance(this).removeListener(this);
			} catch (Exception e) {
			}
			// lancement de l'ecran accueil
			handler.post(splashScreenEndRunnable);

		}
	}

	/**
	 * @return le temps d'affichage du splashscreen, si negatif alors temps
	 *         ecoule
	 */
	private long getTimeToWait() {
		long currentTime = System.currentTimeMillis();
		long timeWaited = currentTime - this.timeStarted;
		long timeToWait = MIN_TIME_TO_DISPLAY - timeWaited;

		return timeToWait;

	}

	/*
	 * 
	 * lancement de l'ecran accueil
	 */
	private void launchHomeScreen() {
		Intent intent = new Intent(this, Accueil.class);
		startActivity(intent);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see fr.mehfile.api.update.UpdateListener#onUpdateComplete()
	 */
	public void onUpdateComplete() {
		if (timeElapsed == false) {
			Utils.debugger.logDebug(TAG, "Update Complete");
			// variable timeElapsed est mise a vrai pour que la methode
			// splashScreenTimeElapsedRunnable ne soit pas execute
			timeElapsed = true;
			// le callback splashScreenTimeElapsedRunnable est retire de la
			// queue
			handler.removeCallbacks(this.splashScreenTimeElapsedRunnable);

			// si le temps minimum est ecoule alors lancement de l'ecan accueil
			// sinon lancement de l'ecran accueil apres le temps restant
			long timeToWait = getTimeToWait();
			if (timeToWait > 0)
				handler.postDelayed(splashScreenEndRunnable, timeToWait);
			else
				handler.post(splashScreenEndRunnable);

		}

	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see fr.mehfile.api.update.UpdateListener#onUpdateError()
	 */
	public void onUpdateError() {

		if (timeElapsed == false) {
			Utils.debugger.logDebug(TAG, "Update Error");
			// variable timeElapsed est mise a vrai pour que la methode
			// splashScreenTimeElapsedRunnable ne soit pas execute
			timeElapsed = true;
			// le callback splashScreenTimeElapsedRunnable est retire de la
			// queue
			handler.removeCallbacks(this.splashScreenTimeElapsedRunnable);

			// si le temps minimum est ecoule alors lancement de l'ecan accueil
			// sinon lancement de l'ecran accueil apres le temps restant
			long timeToWait = getTimeToWait();
			if (timeToWait > 0) {
				// no log
				handler.postDelayed(splashScreenEndWithErrorRunnable,
						timeToWait);
			} else
				handler.post(splashScreenEndWithErrorRunnable);

		}
	}

	/**
	 * lors du clic sur le bouton physique "retour" alors quitter l'application
	 * MZ
	 */
	protected void back() {
		finish();

	}

}